using _RobotInspection.Entities;
using RobotInspection.Entities;
using _RobotInspection.Interfaces;
using _RobotInspection.Models;
using _RobotInspection.DTO;
using SqlSugar;
using Models;

namespace _RobotInspection.Services
{
    public class DailyInspectionManagementService : IDailyInspectionManagementService
    {
        private readonly ISqlSugarClient _db;
        private readonly ILogger<DailyInspectionManagementService> _logger;

        public DailyInspectionManagementService(ISqlSugarClient db, ILogger<DailyInspectionManagementService> logger)
        {
            _db = db;
            _logger = logger;
        }


        /// <summary>
        /// 根据任务ID获取设备详情及点检项次清单
        /// </summary>
        /// <param name="taskId">任务ID</param>
        /// <param name="pageIndex">页码（从1开始，默认1）</param>
        /// <param name="pageSize">页大小（默认20，最大100）</param>
        /// <param name="status">项次状态过滤（可选：1-正常，2-异常，3-待处理）</param>
        /// <returns>设备任务详情及项次分页结果</returns>
        public async Task<ApiResponse<EquipmentTaskDetailDto>> GetTaskDetailsAsync(long taskId, int pageIndex = 1, int pageSize = 20, byte? status = null)
        {
            if (taskId <= 0) return ApiResponse<EquipmentTaskDetailDto>.Error("任务ID不合法", 400);
            try
            {
                var taskInfo = await _db.Queryable<inspection_tasks>()
                    .LeftJoin<equipment>((t, e) => t.equipment_id == e.id)
                    .LeftJoin<users>((t, e, u) => t.assigned_user_id == u.id)
                    .LeftJoin<inspection_plans>((t, e, u, p) => t.plan_id == p.id)
                    .Where((t, e, u, p) => t.id == taskId)
                    .Select((t, e, u, p) => new EquipmentTaskDetailDto
                    {
                        TaskId = t.id,
                        TaskDate = t.task_date,
                        TaskStatus = t.task_status,
                        EquipmentId = e.id,
                        EquipmentName = e.equipment_name,
                        Unit = e.unit,
                        AssignedUserId = u.id,
                        AssignedUserName = u.real_name,
                        StartTime = t.start_time,
                        EndTime = t.end_time,
                        PlanId = t.plan_id,
                        PlanName = p.plan_name,
                        PlanType = p.plan_type
                    }).FirstAsync();

                if (taskInfo == null) return ApiResponse<EquipmentTaskDetailDto>.Error("任务不存在", 404);

                if (pageIndex < 1) pageIndex = 1;
                if (pageSize < 1) pageSize = 20;
                if (pageSize > 100) pageSize = 100;

                var recordsQuery = _db.Queryable<inspection_records>()
                    .LeftJoin<inspection_items>((r, i) => r.item_id == i.id)
                    .Where((r, i) => r.task_id == taskId)
                    .WhereIF(status.HasValue, (r, i) => r.result_status == status.Value);

                var totalCount = await recordsQuery.CountAsync();

                var recordsRaw = await recordsQuery
                    .Select((r, i) => new
                    {
                        RecordId = r.id,
                        ItemId = i.id,
                        ItemName = i.item_name,
                        ItemDescription = i.item_description,
                        StandardValue = i.standard_value,
                        Unit = i.unit,
                        ActualValue = r.actual_value,
                        ResultStatus = r.result_status,
                        Remark = r.remark,
                        CreatedAt = r.created_at,
                        UpdatedAt = r.updated_at
                    }).ToPageListAsync(pageIndex, pageSize);

                var records = recordsRaw.Select(x => new InspectionRecordItemDto
                {
                    RecordId = x.RecordId,
                    ItemId = x.ItemId,
                    ItemName = x.ItemName,
                    ItemDescription = x.ItemDescription,
                    StandardValue = x.StandardValue,
                    Unit = x.Unit,
                    ActualValue = x.ActualValue,
                    ResultStatus = x.ResultStatus,
                    Remark = x.Remark,
                    CreatedAt = x.CreatedAt,
                    UpdatedAt = x.UpdatedAt
                }).ToList();

                taskInfo.Records = records;
                // taskInfo.TotalCount = totalCount;
                return ApiResponse<EquipmentTaskDetailDto>.Success(taskInfo, "操作成功", totalCount);
            }
            catch (Exception ex)
            {
                return ApiResponse<EquipmentTaskDetailDto>.Error($"查询失败：{ex.Message}");
            }
        }
        /// <summary>
        /// 更新或保存点检项次执行结果（支持巡检照片、修复图片、异常责任方、关注事项）
        /// </summary>
        /// <param name="taskId">任务ID</param>
        /// <param name="actualValue">实际值</param>
        /// <param name="resultStatus">结果状态：1-正常，2-异常，3-待处理</param>
        /// <param name="remark">备注</param>
        /// <param name="inspectionPhoto">巡检照片文件（可选）</param>
        /// <param name="repairPhoto">修复图片文件（可选，异常时可上传）</param>
        /// <param name="inspectionTime">检查时间（可选，不传默认当前时间）</param>
        /// <param name="issueDescription">问题描述（异常时建议填写）</param>
        /// <param name="nextAssignParty">下一步责任方（异常时必填，用于创建异常记录）</param>
        /// <param name="inspectorId">检查人ID（可选）</param>
        /// <param name="addAttentionItem">是否添加到关注事项（可选）</param>
        /// <param name="attentionAbnormalName">关注事项的异常名称（添加关注事项时建议填写）</param>
        /// <param name="attentionDescription">关注事项的异常描述（添加关注事项时可选）</param>
        /// <param name="reporterUserId">关注事项上报人ID（可选，默认使用 inspectorId）</param>
        /// <param name="recordId">点检记录ID（必填；按主键更新并校验所属任务）</param>
        /// <returns>保存结果</returns>
        public async Task<ApiResponse<object>> UpsertRecordAsync(long taskId, string actualValue, byte resultStatus, string? remark = null, IFormFile? inspectionPhoto = null, IFormFile? repairPhoto = null, DateTime? inspectionTime = null, string? issueDescription = null, string? nextAssignParty = null, long? inspectorId = null, bool? addAttentionItem = null, string? attentionAbnormalName = null, string? attentionDescription = null, long? reporterUserId = null, long recordId = 0)
        {
            try
            {
                if (recordId <= 0) return ApiResponse<object>.Error("RecordId必填", 400);
                var record = await _db.Queryable<inspection_records>().Where(r => r.id == recordId).FirstAsync();
                if (record == null) return ApiResponse<object>.Error("点检记录不存在", 404);
                if (taskId <= 0) return ApiResponse<object>.Error("TaskId必填", 400);
                if (record.task_id != taskId) return ApiResponse<object>.Error("记录不属于该任务", 400);

                // 保存文件到 wwwroot 静态目录，并在数据库记录 Web 可访问路径
                string? webPath = null;
                string? repairWebPath = null;
                if (inspectionPhoto != null)
                {
                    if (!inspectionPhoto.ContentType.StartsWith("image/"))
                    {
                        return ApiResponse<object>.Error("文件类型不是图片", 400);
                    }
                    string webRoot = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot");
                    var dt = inspectionTime ?? DateTime.Now;
                    string saveDir = Path.Combine(webRoot, "inspection-photos", dt.ToString("yyyy"), dt.ToString("MM"), dt.ToString("dd"));
                    if (!Directory.Exists(saveDir)) Directory.CreateDirectory(saveDir);
                    string fileName = $"{Guid.NewGuid()}_{Path.GetFileName(inspectionPhoto.FileName)}";
                    string physicalPath = Path.Combine(saveDir, fileName);
                    using (var stream = new FileStream(physicalPath, FileMode.Create))
                    {
                        await inspectionPhoto.CopyToAsync(stream);
                    }
                    webPath = $"/inspection-photos/{dt:yyyy}/{dt:MM}/{dt:dd}/{fileName}";
                }

                if (repairPhoto != null)
                {
                    if (!repairPhoto.ContentType.StartsWith("image/"))
                    {
                        return ApiResponse<object>.Error("修复图片类型不是图片", 400);
                    }
                    string webRoot = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot");
                    var dt = inspectionTime ?? DateTime.Now;
                    string saveDir = Path.Combine(webRoot, "repair-photos", dt.ToString("yyyy"), dt.ToString("MM"), dt.ToString("dd"));
                    if (!Directory.Exists(saveDir)) Directory.CreateDirectory(saveDir);
                    string fileName = $"{Guid.NewGuid()}_{Path.GetFileName(repairPhoto.FileName)}";
                    string physicalPath = Path.Combine(saveDir, fileName);
                    using (var stream = new FileStream(physicalPath, FileMode.Create))
                    {
                        await repairPhoto.CopyToAsync(stream);
                    }
                    repairWebPath = $"/repair-photos/{dt:yyyy}/{dt:MM}/{dt:dd}/{fileName}";
                }

                // 统一保存 inspection_records（更新）
                record.actual_value = actualValue;
                record.result_status = resultStatus;
                record.remark = remark;
                record.inspection_photo_path = webPath ?? record.inspection_photo_path;
                record.repair_photo_path = repairWebPath ?? record.repair_photo_path;
                record.inspection_time = inspectionTime ?? record.inspection_time ?? DateTime.Now;
                record.issue_description = issueDescription ?? record.issue_description;
                record.next_assign_party = nextAssignParty ?? record.next_assign_party;
                record.inspector_id = inspectorId ?? record.inspector_id;
                record.updated_at = DateTime.Now;
                var savedRecord = await _db.Updateable(record).ExecuteReturnEntityAsync();

                var messages = new List<string>();
                messages.Add("记录更新成功");

                // 异常时创建异常记录
                if (resultStatus == 2)
                {
                    if (string.IsNullOrWhiteSpace(nextAssignParty))
                    {
                        messages.Add("异常记录未创建：缺少下一步责任方");
                    }
                    else
                    {
                        var abnormalExists = await _db.Queryable<abnormal_records>().Where(a => a.record_id == savedRecord.id).CountAsync();
                        if (abnormalExists == 0)
                        {
                            var abnormal = new abnormal_records
                            {
                                record_id = savedRecord.id,
                                handler_id = inspectorId,
                                handle_description = issueDescription,
                                handle_status = 0,
                                handle_time = null,
                                created_at = DateTime.Now,
                                updated_at = DateTime.Now
                            };
                            await _db.Insertable(abnormal).ExecuteCommandAsync();
                            messages.Add("异常记录已创建");
                        }
                        else
                        {
                            messages.Add("异常记录已存在");
                        }
                    }
                }

                // 添加关注事项
                if (addAttentionItem.HasValue && addAttentionItem.Value)
                {
                    var reporter = reporterUserId ?? inspectorId;
                    if (!reporter.HasValue || reporter.Value <= 0)
                    {
                        messages.Add("关注事项未创建：缺少上报人ID");
                    }
                    else
                    {
                        var abnormalName = string.IsNullOrWhiteSpace(attentionAbnormalName) ? (string.IsNullOrWhiteSpace(issueDescription) ? "点检关注" : issueDescription) : attentionAbnormalName;
                        var attention = new attention_item
                        {
                            record_id = savedRecord.id,
                            user_id = reporter.Value,
                            abnormal_name = abnormalName,
                            abnormal_description = string.IsNullOrWhiteSpace(attentionDescription) ? issueDescription : attentionDescription,
                            reported_at = DateTime.Now
                        };
                        await _db.Insertable(attention).ExecuteCommandAsync();
                        messages.Add("关注事项已创建");
                    }
                }

                var message = string.Join("；", messages);
                return ApiResponse<object>.Success(savedRecord, message);
            }
            catch (Exception ex)
            {
                return ApiResponse<object>.Error($"保存记录失败：{ex.Message}", 500);
            }
        }


        /// <summary>
        /// 根据用户与日期查询设备（按任务的 plan_id 与 equipment_id 关联计划与设备），
        /// 并通过 inspection_plan_items 与 inspection_records 统计该设备当日点检项次总数与已完成数。
        /// </summary>
        /// <param name="userId">用户ID</param>
        /// <param name="date">目标日期</param>
        /// <param name="planType">计划类型过滤：1-日，2-周，3-月，4-一次性</param>
        /// <param name="keyword">设备名称或编码模糊查询</param>
        /// <param name="statusFilter">完成状态过滤：1-已完成，0-未完成</param>
        /// <returns>（含总项次与完成项次）</returns>
        /// <summary>
        /// 根据用户与日期查询设备卡片摘要（按任务与设备关联），统计当天点检项次总数与已完成数
        /// </summary>
        /// <param name="userId">用户ID</param>
        /// <param name="date">目标日期</param>
        /// <param name="planType">计划类型过滤：1-日，2-周，3-月，4-一次性</param>
        /// <param name="keyword">设备名称或编码模糊查询</param>
        /// <param name="statusFilter">完成状态过滤：1-已完成，0-未完成</param>
        /// <returns>设备卡片摘要列表（含总项次与完成项次）</returns>
        public async Task<ApiResponse<List<DailyEquipmentSummaryDto>>> GetUserDailyEquipmentSummaryAsync(long userId, DateTime date, byte? planType = null, string? keyword = null, byte? statusFilter = null)
        {
            try
            {
                /*&& t.task_date.Date == date.Date */
                var list = await _db.Queryable<inspection_tasks>()
                    .InnerJoin<equipment_user_relations>((t, eu) => t.equipment_id == eu.equipment_id)
                    .LeftJoin<equipment>((t, eu, e) => t.equipment_id == e.id)
                    .LeftJoin<inspection_plans>((t, eu, e, p) => t.plan_id == p.id)
                    .Where((t, eu, e, p) => t.assigned_user_id == userId && eu.user_id == userId && eu.is_active == 1)
                    .WhereIF(planType.HasValue, (t, eu, e, p) => p.plan_type == planType.Value)
                    .WhereIF(!string.IsNullOrWhiteSpace(keyword), (t, eu, e, p) => e.equipment_name.Contains(keyword) || e.equipment_code.Contains(keyword))
                    .Select((t, eu, e, p) => new
                    {
                        TaskId = t.id,
                        EquipmentId = e.id,
                        EquipmentName = e.equipment_name,
                        EquipmentCode = e.equipment_code,
                        CompanyName = e.company_name,
                        Unit = e.unit,
                        PlanId = p.id,
                        PlanName = p.plan_name,
                        PlanType = p.plan_type,
                        FrequencyValue = p.frequency_value,
                        SpecificPeriod = p.specific_period,
                        TaskStatus = t.task_status,
                        StartTime = t.start_time,
                        EndTime = t.end_time,
                        TotalCount = SqlFunc.Subqueryable<inspection_plan_items>()
                            .Where(pi => pi.plan_id == t.plan_id && pi.equipment_id == t.equipment_id && pi.item_id != null)
                            .Count(),
                        DoneCount = SqlFunc.Subqueryable<inspection_records>()
                            .Where(r => r.task_id == t.id && (SqlFunc.IsNullOrEmpty(r.actual_value) == false || r.result_status == 1 || r.result_status == 2))
                            .Count()
                    }).ToListAsync();

                var result = list.Select(x => new DailyEquipmentSummaryDto
                {
                    TaskId = x.TaskId,
                    EquipmentId = x.EquipmentId,
                    EquipmentName = x.EquipmentName,
                    EquipmentCode = x.EquipmentCode,
                    CompanyName = x.CompanyName,
                    Unit = x.Unit,
                    PlanId = x.PlanId,
                    PlanName = x.PlanName,
                    PlanType = x.PlanType,
                    PlanTypeName = x.PlanType switch { 1 => "日点检", 2 => "周点检", 3 => "月点检", 4 => "一次性点检", _ => "未知类型" },
                    FrequencyValue = x.FrequencyValue,
                    SpecificPeriod = x.SpecificPeriod,
                    TaskStatus = x.TaskStatus,
                    StartTime = x.StartTime,
                    EndTime = x.EndTime,
                    TotalCount = x.TotalCount,
                    DoneCount = x.DoneCount,
                    IsCompleted = (x.DoneCount == x.TotalCount && x.TotalCount > 0) ? 1 : 0
                }).ToList();

                if (statusFilter.HasValue)
                {
                    result = result.Where(r => (statusFilter.Value == 1 && r.IsCompleted == 1) || (statusFilter.Value == 0 && r.IsCompleted == 0)).ToList();
                }

                return ApiResponse<List<DailyEquipmentSummaryDto>>.Success(result, null, result.Count);
            }
            catch (Exception ex)
            {
                return ApiResponse<List<DailyEquipmentSummaryDto>>.Error($"查询失败：{ex.Message}");
            }
        }

        /// <summary>
        /// 根据记录ID获取点检详情
        /// </summary>
        /// <param name="recordId">记录ID</param>
        /// <returns>点检记录详情</returns>
        /// <summary>
        /// 根据点检记录ID获取执行详情（联表项次、任务、设备与人员）
        /// </summary>
        /// <param name="recordId">记录ID</param>
        /// <returns>点检记录详情</returns>
        public async Task<ApiResponse<InspectionRecordDetailDto>> GetRecordByIdAsync(long recordId)
        {
            if (recordId <= 0) return ApiResponse<InspectionRecordDetailDto>.Error("记录ID不合法", 400);
            try
            {
                var rec = await _db.Queryable<inspection_records>()
                    .LeftJoin<inspection_items>((r, i) => r.item_id == i.id)
                    .LeftJoin<inspection_tasks>((r, i, t) => r.task_id == t.id)
                    .LeftJoin<equipment>((r, i, t, e) => t.equipment_id == e.id)
                    .LeftJoin<users>((r, i, t, e, ui) => r.inspector_id == ui.id)
                    .LeftJoin<users>((r, i, t, e, ui, ur) => r.repair_user_id == ur.id)
                    .Where((r, i, t, e, ui, ur) => r.id == recordId)
                    .Select((r, i, t, e, ui, ur) => new InspectionRecordDetailDto
                    {
                        RecordId = r.id,
                        TaskId = r.task_id,
                        ItemId = i.id,
                        InspectionTitle = r.inspection_title,
                        InspectionContent = r.inspection_content,
                        ItemName = i.item_name,
                        ItemDescription = i.item_description,
                        StandardValue = i.standard_value,
                        Unit = i.unit,
                        ActualValue = r.actual_value,
                        ResultStatus = r.result_status,
                        Remark = r.remark,
                        InspectionPhotoPath = r.inspection_photo_path,
                        InspectionTime = r.inspection_time,
                        IssueDescription = r.issue_description,
                        NextAssignParty = r.next_assign_party,
                        WorkOrderNo = r.work_order_no,
                        InspectorId = r.inspector_id,
                        InspectorName = ui.real_name,
                        RepairPhotoPath = r.repair_photo_path,
                        RepairResult = r.repair_result,
                        RepairTime = r.repair_time,
                        RepairUserId = r.repair_user_id,
                        RepairUserName = ur.real_name,
                        EquipmentId = e.id,
                        EquipmentName = e.equipment_name,
                        EquipmentCode = e.equipment_code
                    })
                    .FirstAsync();

                if (rec == null) return ApiResponse<InspectionRecordDetailDto>.Error("记录不存在", 404);
                return ApiResponse<InspectionRecordDetailDto>.Success(rec);
            }
            catch (Exception ex)
            {
                return ApiResponse<InspectionRecordDetailDto>.Error($"查询失败：{ex.Message}", 500);
            }
        }

        /// <summary>
        /// 根据用户与设备在指定日期获取对应任务ID
        /// </summary>
        /// <param name="userId">用户ID</param>
        /// <param name="equipmentId">设备ID</param>
        /// <param name="date">目标日期</param>
        /// <returns>任务ID</returns>
        public async Task<ApiResponse<object>> GetTaskIdForUserAndEquipmentAsync(long userId, long equipmentId, DateTime date)
        {
            try
            {
                var taskId = await _db.Queryable<inspection_tasks>()
                    .InnerJoin<equipment_user_relations>((t, eu) => t.equipment_id == eu.equipment_id)
                    .Where((t, eu) => t.assigned_user_id == userId && eu.user_id == userId && eu.is_active == 1 && t.task_date.Date == date.Date && t.equipment_id == equipmentId)
                    .Select(t => t.id)
                    .FirstAsync();

                if (taskId <= 0)
                {
                    return ApiResponse<object>.Error("未找到对应任务", 404);
                }
                return ApiResponse<object>.Success(new { TaskId = taskId });
            }
            catch (Exception ex)
            {
                return ApiResponse<object>.Error($"查询失败：{ex.Message}", 500);
            }
        }
    }
}
